
#define EPOLL_MODULE
#ifdef EPOLL_MODULE
#include "ra_epoll.c"
#endif

raEventLoop * ra_create_eventloop(unsigned long size){
    raEventLoop *eventloop;
    int         ret; 
    eventloop =  malloc(sizeof(raEventLoop));
    if(eventloop == NULL) goto err;
    eventloop->setsize = size;
    eventloop->stop    = 0;
    eventloop->maxfd   = -1;
    eventloop->apidata = NULL;
    eventloop->events  = malloc(size * sizeof(raFileEvent));
    eventloop->fires   = malloc(size * sizeof(raFiredEvent));
    if(eventloop->events == NULL || eventloop->fires == NULL) goto err;
    ret = ra_create_ApiState(eventloop);
    if(ret != RA_OK) goto err;

    for (size_t i = 0; i < size; i++)
    {
        eventloop->events[i].mask = NONE;
    }
    return eventloop;

err:
    if(eventloop){
        free(eventloop->events);
        free(eventloop->fires);
        free(eventloop);
    }
    return NULL;
}


int ra_add_event(raEventLoop *eventloop,int fd,raFileProc proc,int mask){
    if(eventloop == NULL || fd >= eventloop->setsize)   return RA_ERR;
    raFileEvent * event;
    event = &eventloop->events[fd];
    if(mask & READABLE) {
        event->mask |= READABLE;
        event->rFileProc = proc;
    }
    if(mask & WRITEABLE) {
        event->mask |= WRITEABLE;
        event->wFileProc = proc;
    }
    return ra_add_event_ApiState(eventloop,fd,mask);
}

int ra_del_event(raEventLoop *eventloop,int fd,raFileProc proc,int mask){
    if(eventloop == NULL || fd >= eventloop->setsize)   return RA_ERR;
    raFileEvent * event;
    event = &eventloop->events[fd];
    if(mask & READABLE )  event->mask &= ~READABLE;
    if(mask & WRITEABLE)  event->mask &= ~WRITEABLE;

    return ra_del_event_ApiState(eventloop,fd,mask);
}

raEventLoop * ra_resize_eventloop(raEventLoop * eventloop,unsigned long size){
    if(eventloop == NULL) return NULL;
    if(size <= eventloop->setsize) return eventloop;
    //resize self
    void * tempEvents = malloc(sizeof(raFileEvent)*size);
    void * tempFires = malloc(sizeof(raFiredEvent)*size);
    if(tempEvents == NULL || tempFires == NULL) return NULL;
    memcpy(tempEvents, eventloop->events, sizeof(raFileEvent)  * eventloop->setsize);
    memcpy(tempFires,  eventloop->fires,  sizeof(raFiredEvent) * eventloop->setsize);
    free(eventloop->events);
    free(eventloop->fires);
    eventloop->events = tempEvents;
    eventloop->fires = tempFires;
    eventloop->setsize = size;
    for (int i = eventloop->maxfd + 1; i < eventloop->setsize; i++)
    {
        eventloop->events[i].mask = NONE;
    }
    return eventloop;
}

void ra_free_eventloop(raEventLoop *eventloop) {
    if(eventloop == NULL) return;
    free(eventloop->events);
    free(eventloop->fires);
    ra_free_ApiState(eventloop);
}

int ra_process_events(raEventLoop *eventloop, int flags){
    int processNum,ret;
    ret = processNum = 0;
    //time events
    if(flags & RA_TIME_EVENTS){
        //nothing
    }

    if(flags & RA_FILE_EVENTS){
        if(eventloop->maxfd < 0) return processNum;
        ret = ra_wait(eventloop,NULL);
        if(ret == RA_OK){
            for(int i = 0;i < eventloop->maxfd; ++i){
                int fd   = eventloop->fires[i].fd;
                int mask = eventloop->fires[i].mask;
                raFileEvent * fe = &eventloop->events[fd];
                if(mask & READABLE ){
                    eventloop->events[fd].rFileProc(eventloop,fd);
                    ++processNum;
                }
                if(fe->mask & WRITEABLE || mask & WRITEABLE){
                    eventloop->events[fd].wFileProc(eventloop,fd);
                    ++processNum;
                }
            }
        }
    }
    return processNum;
}

